/**
 * @class ActionWidget
 * @extends StackWidget
 */
var ActionWidget = function(el, config) {
  this._classType = "ActionWidget";
  this.processPanel = config.processPanel;
  this.actionsPanel = this.processPanel.actionsPanel;
  this.actionDef = config.actionDef;
  this.uaction = mb.packages.findUnitAction(this.actionDef.type);
  
  ActionWidget.superclass.constructor.call(this, el, { 
    title : this.actionDef.name + ' (' + this.uaction.label + ')'
  });
  this.addEvents({
    'change' : true,
    'update' : true
  });
  this.render();

  // re-adjust rendered object size
  this.adjustSize();
}


Ext.extend(ActionWidget, StackWidget, {
  render : function() {
    this.renderInputArea();
    this.renderOutputArea();
  }
  ,
  renderInputArea : function() {
    this.inputAreaWrap = this.body.createChild({ cls : 'af-action-input-wrap' });
    this.inputToolbar = new Ext.Toolbar(this.inputAreaWrap.createChild());
    this.inputToolbar.el.enableDisplayMode();
    this.inputToolbar.el.hide();
    this.inputArea = this.inputAreaWrap.createChild({ cls : 'af-action-input' });
    this.inputFields = [];
    this.renderInputFields();
  }
  ,
  renderInputFields : function() {
    if (this.uaction.allowDynamicInput) {
      this.inputToolbar.el.show();
      this.inputToolbar.addButton({
        text: 'Add New Input',
        cls: 'x-btn-text-icon af-add-btn',
        handler : this.createDynamicBindField,
        scope : this
      });
    }
    if (this.uaction.inputs) {
      mb.lang.forEach(
        mb.lang.values(this.uaction.inputs), 
        function(inputDef) { this.createBindField(inputDef) },
        this
      ); 
    }
    mb.lang.forEach(
      mb.lang.keys(this.actionDef.inputs || {}),
      function(key) {
        var field = mb.lang.find(this.inputFields, function(f){ 
          return f.getName() == key 
        });
        if (!field) {
          field = this.createDynamicBindField();
          field.setName(key);
        }
        field.setValue(this.actionDef.inputs[key]);
      },
      this
    );
  }
  ,
  createBindField : function(config) {
    var field = new ActionInputField(this.inputArea.createChild(), config);
    field.on('change', this.handleChangeBinding, this);
    field.on('destroy', this.destroyBindField, this);
    this.inputFields.push(field);
    return field;
  }
  ,
  createDynamicBindField : function() {
    var field = new DynamicActionInputField(this.inputArea.createChild());
    field.on('change', this.handleChangeBinding, this);
    field.on('destroy', this.destroyBindField, this);
    this.inputFields.push(field);
    return field;
  }
  ,
  destroyBindField : function(field) {
    field.un('change', this.handleChangeBinding);
    field.un('destroy', this.destroyBindField);
    this.inputFields = jQuery.grep(this.inputFields, function(f) {
      return f != field;
    });
    this.handleChangeBinding();
  }
  ,
  handleChangeBinding : function() {
    this.actionDef.setInputs(this.getInputValues());
  }
  ,
  getInputValues : function() {
    var inputs = {};
    jQuery.each(this.inputFields, function(i, field) {
      var value = field.getValue();
      if (value) inputs[field.getName()] = value;
    });
    return inputs;
  }
  ,
  renderOutputArea : function() {
    this.outputAreaWrap = this.body.createChild({ cls : 'af-action-output-wrap' });
    this.outputAreaWrap.enableDisplayMode();
    this.outputToolbar = new Ext.Toolbar(this.outputAreaWrap.createChild());
    this.viewSelect = new SelectBox({
      fieldName : 'view mode',
      name : 'viewSelect',
      width : 80,
      options : [ 'Tree', 'Grid' ]
    });
    this.viewSelect.setValue('Tree');
    this.viewSelect.on('select', function() {
      this.changeOutputView(this.viewSelect.getValue());
    }, this);
    this.outputToolbar.add(this.viewSelect);
    this.outputToolbar.addButton({
      text: 'Refresh',
      cls: 'x-btn-text-icon af-refresh-btn',
      handler: this.refresh,
      scope : this
    });
    this.outputArea = this.outputAreaWrap.createChild({ cls : 'af-action-output' });
    this.outputTreeViewEl = this.outputArea.createChild({ cls : 'af-action-output-tree' });
    this.outputTreeViewEl.enableDisplayMode();
    this.outputTreeView = new OutputTreeView(this.outputTreeViewEl, this.actionDef.name, true),
    this.outputGridViewEl = this.outputArea.createChild({ cls : 'af-action-output-grid' });
    this.outputGridViewEl.enableDisplayMode();
    this.outputGridView = new OutputGridView(this.outputGridViewEl, this.actionDef.name, true)
    this.changeOutputView(this.viewSelect.getValue());
  }
  ,
  changeOutputView : function(viewMode) {
    if (viewMode=='Grid') {
      this.outputTreeViewEl.hide();
      this.outputGridViewEl.show();
      this.outputGridView.grid.render();
    } else {
      this.outputGridViewEl.hide();
      this.outputTreeViewEl.show();
    }
  }
  ,
  adjustSize : function() {
    ActionWidget.superclass.adjustSize.apply(this);
    this.outputArea.setWidth(525);
  }
  ,
  refresh : function() {
    this.outputAreaWrap.show();
    this.outputTreeView.prepare(); 
    this.outputGridView.prepare(); 
    this.evaluate(function(value) {
      this.outputTreeView.render(value);
      this.outputGridView.render(value);
    }.createDelegate(this));
  }
  ,
  focus : function() {
    ActionWidget.superclass.focus.call(this);
    if (!this.outputAreaWrap.isVisible()) this.outputAreaWrap.show();
  }
  ,
  blur : function() {
    ActionWidget.superclass.blur.call(this);
    this.outputAreaWrap.hide();
  }
  ,
  // Called to process the Refresh button which evaluates the web service call
  evaluate : function(callback) {
    this.processPanel.process.evaluate('${'+this.actionDef.name+'}', function(response) {
      callback(response.value);
    });
  }
  ,
  clearOutput : function() {
    this.getOutputView().reset();
  }
  ,
  destroy : function() {
    ActionWidget.superclass.destroy.apply(this, arguments);
    this.processPanel.processDef.removeActionDef(this.actionDef.name);
  }
});
